Skip to content

feat: Derive fiat asset from feature flags before hardcoded fallback#8631

Open
OGPoyraz wants to merge 8 commits intomainfrom
ogp/fiat-ff-implementation
Open

feat: Derive fiat asset from feature flags before hardcoded fallback#8631
OGPoyraz wants to merge 8 commits intomainfrom
ogp/fiat-ff-implementation

Conversation

@OGPoyraz
Copy link
Copy Markdown
Member

@OGPoyraz OGPoyraz commented Apr 29, 2026

Explanation

Currently deriveFiatAssetForFiatPayment resolves the fiat asset for a payment entirely from a hardcoded map (FIAT_ASSET_ID_BY_TX_TYPE). This makes it impossible to adjust asset mappings without a code release.

This PR introduces a 3-tier resolution for fiat assets:

  1. Feature flag - reads from confirmations_pay_fiat.assetPerTransactionType[txType] via RemoteFeatureFlagController
  2. Hardcoded map - falls back to the existing FIAT_ASSET_ID_BY_TX_TYPE constant
  3. ETH on mainnet - terminal fallback when neither source has an entry

The function signature gains a messenger parameter (already available at the call site in fiat-quotes.ts), and the return type tightens from TransactionPayFiatAsset | undefined to TransactionPayFiatAsset since the ETH mainnet fallback guarantees a value.

References

  • Feature flag key: confirmations_pay_fiat

Checklist

  • I've updated the test suite for new or updated code as appropriate
  • I've updated documentation (JSDoc, Markdown, etc.) for new or updated code as appropriate
  • I've communicated my changes to consumers by updating changelogs for packages I've changed
  • I've introduced breaking changes in this PR and have prepared draft pull requests for clients and consumer packages to resolve them

Note

Medium Risk
Changes how fiat strategy chooses/identifies its source asset by introducing remote-flag overrides and new CAIP-19 asset ID construction, which could affect quoting/submission if mappings or chain coin types are incorrect.

Overview
Fiat asset selection for MM Pay is refactored to a 3-tier resolution: confirmations_pay_fiat.assetPerTransactionType remote feature flag, then the existing hardcoded FIAT_ASSET_ID_BY_TX_TYPE, then an ETH mainnet fallback (including improved handling of batch transactions by scanning nested tx types).

Fiat quote/submit flows and TransactionPayController token selection now derive the RampsController assetId via a new buildCaipAssetType(chainId, address) helper (SLIP-44 for native tokens with chain overrides, ERC-20 otherwise) and pull token decimals from getTokenInfo instead of embedding them in fiat-asset constants; tests/changelog are updated accordingly.

Reviewed by Cursor Bugbot for commit c66a60a. Bugbot is set up for automated code reviews on this repo. Configure here.

@OGPoyraz OGPoyraz requested review from a team as code owners April 29, 2026 10:47
@OGPoyraz OGPoyraz force-pushed the ogp/fiat-ff-implementation branch from 5425439 to b24eac7 Compare April 29, 2026 10:48
@OGPoyraz OGPoyraz changed the title feat: read fiat asset from feature flags before hardcoded fallback feat: Derive fiat asset from feature flags before hardcoded fallback Apr 29, 2026
@OGPoyraz OGPoyraz force-pushed the ogp/fiat-ff-implementation branch 2 times, most recently from 7ef80a6 to 1096df7 Compare April 29, 2026 11:03
import type { TransactionPayFiatAsset } from './constants';
import { ETH_MAINNET_FIAT_ASSET, FIAT_ASSET_ID_BY_TX_TYPE } from './constants';

function resolveTransactionType(
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Minor, exported functions at top of file for readability?

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done

transaction: TransactionMeta,
): TransactionType | undefined {
if (transaction.type === TransactionType.batch) {
return transaction.nestedTransactions?.[0]?.type;
Copy link
Copy Markdown
Member

@matthewwalsh0 matthewwalsh0 May 1, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is it safe to assume this is always the first call?

Don't we iterate over calls looking for a supported type in Relay strategy?

In Predict for example, if first deposit, the initial call is the deploy for Safe proxy?

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done, added a similar utility

const firstMatchingType = transaction.nestedTransactions?.[0]?.type;
if (firstMatchingType) {
return FIAT_ASSET_ID_BY_TX_TYPE[firstMatchingType];
const hardcodedAsset = FIAT_ASSET_ID_BY_TX_TYPE[txType];
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The intent of the feature-flag utils is to abstract these defaults also, so most of the existing functions fallback to defaults.

Can we do that here and encapsulate the constant and mainnet fallbacks in there?

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good call, carried over the fallbacks info FF utility

transactionType: TransactionType,
): TransactionPayFiatAsset | undefined {
const state = messenger.call('RemoteFeatureFlagController:getState');
const fiatFlags = state.remoteFeatureFlags?.confirmations_pay_fiat as
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should we define a local FiatFlags type at the top of the file for re-use and readability?

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done

Copy link
Copy Markdown

@cursor cursor Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Cursor Bugbot has reviewed your changes and found 2 potential issues.

Fix All in Cursor

❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, have a team admin enable autofix in the Cursor dashboard.

Reviewed by Cursor Bugbot for commit 0c647d8a23669a02f76637ef87693291937c1505. Configure here.

Comment thread packages/transaction-pay-controller/src/strategy/fiat/utils.ts
Comment thread packages/transaction-pay-controller/src/utils/token.ts
@OGPoyraz OGPoyraz force-pushed the ogp/fiat-ff-implementation branch from 0c647d8 to 469e1c7 Compare May 5, 2026 09:07
@OGPoyraz OGPoyraz requested a review from matthewwalsh0 May 5, 2026 10:28
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants